home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / GCC / V2-4-5 / GPPLIBSR00 / cc / strstream < prev   
Text File  |  1993-12-08  |  6KB  |  234 lines

  1. //    This is part of the iostream library, providing input/output for C++.
  2. //    Copyright (C) 1991 Per Bothner.
  3. //
  4. //    This library is free software; you can redistribute it and/or
  5. //    modify it under the terms of the GNU Library General Public
  6. //    License as published by the Free Software Foundation; either
  7. //    version 2 of the License, or (at your option) any later version.
  8. //
  9. //    This library is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. //    Library General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU Library General Public
  15. //    License along with this library; if not, write to the Free
  16. //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #ifdef __GNUG__
  19. #pragma implementation "strstream.h"
  20. #endif
  21. #include "ioprivate.h"
  22. #include "strstream.h"
  23.  
  24. static void* default_alloc(_G_size_t size)
  25. {
  26.     return (void*)new char[size];
  27. }
  28.  
  29. static void default_free(void* ptr)
  30. {
  31.     delete [] (char*)ptr;
  32. }
  33.  
  34. istrstream::istrstream(const char *cp, int n)
  35. {
  36.     init(new strstreambuf(cp, n));
  37. }
  38.  
  39. ostrstream::ostrstream()
  40. {
  41.     init(new strstreambuf());
  42. }
  43.  
  44. strstreambase::strstreambase(char *cp, int n, int mode)
  45. {
  46.     char *pstart;
  47.     if (mode == ios::app || mode == ios::ate)
  48.     pstart = cp + strlen(cp);
  49.     else
  50.     pstart = cp;
  51.     init(new strstreambuf(cp, n, pstart));
  52. }
  53.  
  54. char *strstreambuf::str()
  55. {
  56.     freeze(1);
  57.     return base();
  58. }
  59.  
  60. _G_size_t strstreambuf::pcount()
  61. {
  62.     _G_size_t put_len = pptr() - pbase();
  63.     if (put_len < _len) put_len = _len;
  64.     return put_len;
  65. }
  66.  
  67. int strstreambuf::overflow(int c /* = EOF */)
  68. {
  69.   const int flush_only = c == EOF;
  70.   if (_flags & _S_NO_WRITES)
  71.       return flush_only ? 0 : EOF;
  72.   size_t pos = pptr() - pbase();
  73.   size_t get_pos = gptr() - pbase();
  74.   if (pos > _len) _len = pos;
  75.   if (pos >= blen() + flush_only) {
  76.       char *new_buf;
  77.       size_t new_size = 2 * blen();
  78.       if (frozen()) /* not allowed to enlarge */
  79.       return EOF;
  80.       new_buf = (char*)(*_allocate_buffer)(new_size);
  81.       memcpy(new_buf, base(), blen());
  82.       if (new_buf == NULL) {
  83. //      __ferror(fp) = 1;
  84.       return EOF;
  85.       }
  86. #if 0
  87.       if (lenp == &_len) /* use '\0'-filling */
  88.       memset(new_buf + pos, 0, blen() - pos);
  89. #endif
  90.       if (_base) {
  91.       (*_free_buffer)(_base);
  92.       _base = NULL; // So setb() won't try to delete _base.
  93.       }
  94.       setb(new_buf, new_buf + new_size, 1);
  95.     }
  96.  
  97.   setp(base(), ebuf());
  98.   pbump(pos);
  99.   setg(base(), base() + get_pos, base() + _len);
  100.   if (!flush_only) {
  101.       *pptr() = (unsigned char) c;
  102.       pbump(1);
  103.   }
  104.   return c;
  105. }
  106.  
  107. int strstreambuf::underflow()
  108. {
  109.     size_t ppos = pptr() - pbase();
  110.     if (ppos > _len) _len = ppos;
  111.     setg(base(), gptr(), base() + _len);
  112.     if (gptr() < egptr())
  113.     return *gptr();
  114.     else
  115.     return EOF;
  116. }
  117.  
  118.  
  119. void strstreambuf::init_dynamic(_alloc_type alloc, _free_type free,
  120.                 int initial_size)
  121.                 
  122. {
  123.     _len = 0;
  124.     if (initial_size < 16)
  125.     initial_size = 16;
  126.     _allocate_buffer = alloc ? alloc : default_alloc;
  127.     _free_buffer = free ? free : default_free;
  128.     char * buf = (char*)(*_allocate_buffer)(initial_size);
  129.     setb(buf, buf + initial_size, 1);
  130.     setp(buf, buf + initial_size);
  131.     setg(buf, buf, buf);
  132. }
  133.  
  134. void strstreambuf::init_static(char *ptr, int size, char *pstart)
  135. {
  136.     if (size == 0)
  137.     size = strlen(ptr);
  138.     else if (size < 0) {
  139.     // If size is negative 'the characters are assumed to
  140.     // continue indefinitely.'  This is kind of messy ...
  141. #if 1
  142.     size = 512;
  143.     // Try increasing powers of 2, as long as we don't wrap around.
  144.     // This can lose in pathological cases (ptr near the end
  145.     // of the address space).  A better solution might be to
  146.     // adjust the size on underflow/overflow.  FIXME.
  147.     for (int s; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
  148.         size = s;
  149.     size = s;
  150. #else
  151.     // The following semi-portable kludge assumes that
  152.     // sizeof(unsigned long) == sizeof(char*). Hence,
  153.     // (unsigned long)(-1) should be the largest possible address.
  154.     unsigned long highest = (unsigned long)(-1);
  155.     // Pointers are signed on some brain-damaged systems, in
  156.     // which case we divide by two to get the maximum signed address.
  157.     if  ((char*)highest < ptr)
  158.         highest >>= 1;
  159.     size = (char*)highest - ptr;
  160. #endif
  161.     }
  162.     setb(ptr, ptr+size);
  163.     if (pstart) {
  164.     setp(ptr, ebuf());
  165.     pbump(pstart-ptr);
  166.     setg(ptr, ptr, pstart);
  167.     }
  168.     else {
  169.     setp(ptr, ptr); 
  170.     setg(ptr, ptr, ebuf());
  171.     }
  172.     _len = egptr() - ptr;
  173. }
  174.  
  175. strstreambuf::~strstreambuf()
  176. {
  177.     if (_base && !(_flags & _S_USER_BUF))
  178.         (_free_buffer)(_base);
  179.     _base = NULL;
  180. }
  181.  
  182. streampos strstreambuf::seekoff(streamoff off, _seek_dir dir,
  183.                     int mode /*=ios::in|ios::out*/)
  184. {
  185.     _allocate_buffer = default_alloc;
  186.     _free_buffer = default_free;
  187.     size_t cur_size = pcount();
  188.     streampos new_pos = EOF;
  189.  
  190.     // Move the get pointer, if requested.
  191.     if (mode & ios::in) {
  192.     switch (dir) {
  193.       case ios::end:
  194.         off += cur_size;
  195.         break;
  196.       case ios::cur:
  197.         off += gptr() - pbase();
  198.         break;
  199.       default: /*case ios::beg: */
  200.         break;
  201.     }
  202.     if (off < 0 || (size_t)off > cur_size)
  203.         return EOF;
  204.     setg(base(), base() + off, base() + cur_size);
  205.     new_pos = off;
  206.     }
  207.  
  208.     // Move the put pointer, if requested.
  209.     if (mode & ios::out) {
  210.     switch (dir) {
  211.       case ios::end:
  212.         off += cur_size;
  213.         break;
  214.       case ios::cur:
  215.         off += pptr() - pbase();
  216.         break;
  217.       default: /*case ios::beg: */
  218.         break;
  219.     }
  220.     if (off < 0 || (size_t)off > cur_size)
  221.         return EOF;
  222.     pbump(base() + off - pptr());
  223.     new_pos = off;
  224.     }
  225.     return new_pos;
  226. }
  227.  
  228. int strstreambuf::pbackfail(int c)
  229. {
  230.     if ((_flags & _S_NO_WRITES) && c != EOF)
  231.     return EOF;
  232.     return backupbuf::pbackfail(c);
  233. }
  234.